home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Games Collection 1 / software vault.zip / software vault / CDR10 / XLIB06.ZIP / XRECT.ASM < prev    next >
Assembly Source File  |  1993-09-13  |  25KB  |  685 lines

  1. ;-----------------------------------------------------------------------
  2. ; MODULE XRECT
  3. ;
  4. ; Rectangle functions all MODE X 256 Color resolutions
  5. ;
  6. ; Compile with Tasm.
  7. ; C callable.
  8. ;
  9. ;
  10. ; ****** XLIB - Mode X graphics library                ****************
  11. ; ******                                               ****************
  12. ; ****** Written By Themie Gouthas                     ****************
  13. ;
  14. ; egg@dstos3.dsto.gov.au
  15. ; teg@bart.dsto.gov.au
  16. ;-----------------------------------------------------------------------
  17.  
  18.  
  19. include xlib.inc
  20. include xrect.inc
  21.  
  22.  
  23.     .data
  24. ; Plane masks for clipping left and right edges of rectangle.
  25.         LeftClipPlaneMask       db      00fh,00eh,00ch,008h
  26.     RightClipPlaneMask      db      00fh,001h,003h,007h
  27.     .code
  28.  
  29. ;---------------------------------------------------------------------------
  30. ; Mode X (320x240, 256 colors) rectangle solid colour fill routine.
  31. ;
  32. ; Based on code originally published in DDJ Mag by M. Abrash
  33. ;
  34. ; with TASM 2. C near-callable as:
  35. ;
  36. ;    void x_rect_fill_clipped(int StartX, int StartY, int EndX, int EndY,
  37. ;       unsigned int PageBase, unsigne int color);
  38. ;
  39. ;
  40.  
  41.  
  42. _x_rect_fill_clipped proc
  43. ARG     StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word
  44.     push bp              ;preserve caller's stack frame
  45.     mov  bp,sp           ;point to local stack frame
  46.     push si              ;preserve caller's register variables
  47.     push di
  48.  
  49.     mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top
  50.     mov   cx,[_BottomClip]
  51.     mov   ax,[StartY]
  52.     mov   bx,[EndY]
  53.         cmp   dx,ax
  54.         jle   @@CheckBottomClip
  55.     cmp   dx,bx
  56.     jg    @@NotVisible
  57.     mov   [StartY],dx
  58.  
  59. @@CheckBottomClip:
  60.     cmp   cx,bx
  61.     jg    @@CheckLeftClip
  62.     cmp   cx,ax
  63.     jl    @@NotVisible
  64.     mov   [EndY],cx
  65.  
  66. @@CheckLeftClip:
  67.     mov   dx,[_LeftClip]           ; Compare u.l. Y coord with Top
  68.     mov   cx,[_RightClip]
  69.     mov   ax,[StartX]
  70.     mov   bx,[EndX]
  71.     sal   dx,2
  72.     sal   cx,2
  73.     cmp   dx,ax
  74.     jle   @@CheckRightClip
  75.     cmp   dx,bx
  76.     jg    @@NotVisible
  77.     mov   [StartX],dx
  78.  
  79. @@CheckRightClip:
  80.     cmp   cx,bx
  81.     jg    RFClipDone
  82.     cmp   cx,ax
  83.     jl    @@NotVisible
  84.     mov   [EndX],cx
  85.     jmp   RFClipDone
  86.  
  87. @@NotVisible:
  88.     mov   ax,1
  89.     pop   di                          ; restore registers
  90.     pop   si
  91.     pop   bp
  92.     ret
  93. _x_rect_fill_clipped endp
  94.  
  95.  
  96.  
  97. ;---------------------------------------------------------------------------
  98. ; Mode X (320x240, 256 colors) rectangle solid colour fill routine.
  99. ;
  100. ; Based on code originally published in DDJ Mag by M. Abrash
  101. ;
  102. ; with TASM 2. C near-callable as:
  103. ;
  104. ;    void x_rect_fill(int StartX, int StartY, int EndX, int EndY,
  105. ;       unsigned int PageBase, unsigne int color);
  106. ;
  107. ;
  108.  
  109.  
  110. _x_rect_fill proc
  111. ARG     StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Color:word
  112.     push bp              ;preserve caller's stack frame
  113.     mov  bp,sp           ;point to local stack frame
  114.     push si              ;preserve caller's register variables
  115.     push di
  116.  
  117. RFClipDone:
  118.     cld
  119.     mov  ax,[_ScrnLogicalByteWidth]
  120.     mul  [StartY]            ;offset in page of top rectangle scan line
  121.     mov  di,[StartX]
  122.     sar  di,2                ;X/4 = offset of first rectangle pixel in scan
  123.     add  di,ax               ;offset of first rectangle pixel in page
  124.     add  di,[PageBase]       ;offset of first rectangle pixel in
  125.                      ; display memory
  126.     mov  ax,SCREEN_SEG       ;point ES:DI to the first rectangle
  127.     mov  es,ax               ; pixel's address
  128.     mov  dx,SC_INDEX         ;set the Sequence Controller Index to
  129.     mov  al,MAP_MASK         ; point to the Map Mask register
  130.     out  dx,al
  131.     inc  dx                  ;point DX to the SC Data register
  132.     mov  si,[StartX]
  133.     and  si,0003h                    ;look up left edge plane mask
  134.     mov  bh,LeftClipPlaneMask[si]    ; to clip & put in BH
  135.     mov  si,[EndX]
  136.     and  si,0003h                    ;look up right edge plane
  137.     mov  bl,RightClipPlaneMask[si]   ; mask to clip & put in BL
  138.  
  139.     mov  cx,[EndX]                   ;calculate # of addresses across rect
  140.     mov  si,[StartX]
  141.     cmp  cx,si
  142.     jle  @@FillDone                  ;skip if 0 or negative width
  143.     dec  cx
  144.     and  si,not 011b
  145.     sub  cx,si
  146.     sar  cx,2                 ;# of addresses across rectangle to fill - 1
  147.     jnz  @@MasksSet           ;there's more than one byte to draw
  148.     and  bh,bl                ;there's only one byte, so combine the left
  149.                                   ; and right edge clip masks
  150. @@MasksSet:
  151.     mov  si,[EndY]
  152.     sub  si,[StartY]            ;BX = height of rectangle
  153.     jle  @@FillDone             ;skip if 0 or negative height
  154.     mov  ah,byte ptr [Color]    ;color with which to fill
  155.     mov  bp,[_ScrnLogicalByteWidth]  ;stack frame isn't needed any more
  156.     sub  bp,cx                  ;distance from end of one scan line to start
  157.     dec  bp                     ; of next
  158. @@FillRowsLoop:
  159.     push cx                     ;remember width in addresses - 1
  160.     mov  al,bh                  ;put left-edge clip mask in AL
  161.     out  dx,al                  ;set the left-edge plane (clip) mask
  162.     mov  al,ah                  ;put color in AL
  163.     stosb                       ;draw the left edge
  164.     dec  cx                     ;count off left edge byte
  165.     js   @@FillLoopBottom       ;that's the only byte
  166.     jz   @@DoRightEdge          ;there are only two bytes
  167.     mov  al,00fh                ;middle addresses drawn 4 pixels at a pop
  168.     out  dx,al                  ;set the middle pixel mask to no clip
  169.     mov  al,ah                  ;put color in AL
  170.     rep  stosb                  ;draw middle addresses four pixels apiece
  171. @@DoRightEdge:
  172.     mov  al,bl                  ;put right-edge clip mask in AL
  173.     out  dx,al                  ;set the right-edge plane (clip) mask
  174.     mov  al,ah                  ;put color in AL
  175.         stosb                       ;draw the right edge
  176. @@FillLoopBottom:
  177.     add  di,bp                  ;point to start of the next scan line of
  178.                                     ; the rectangle
  179.     pop  cx                     ;retrieve width in addresses - 1
  180.     dec  si                     ;count down scan lines
  181.     jnz  @@FillRowsLoop
  182. @@FillDone:
  183.     pop  di                     ;restore caller's register variables
  184.     pop  si
  185.     pop  bp                     ;restore caller's stack frame
  186.         ret
  187. _x_rect_fill endp
  188.  
  189.  
  190.  
  191. ;---------------------------------------------------------------------------
  192. ; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.
  193. ; Upper left corner of pattern is always aligned to a multiple-of-4
  194. ; row and column. Works on all VGAs. Uses approach of copying the
  195. ; pattern to off-screen display memory, then loading the latches with
  196. ; the pattern for each scan line and filling each scan line four
  197. ; pixels at a time. Fills up to but not including the column at EndX
  198. ; and the row at EndY. No clipping is performed. All ASM code tested
  199. ;
  200. ;
  201. ; Based on code originally published in DDJ Mag by M. Abrash
  202. ;
  203. ;
  204. ;  C near-callable as:
  205. ;
  206. ;    void x_rect_pattern_clipped(int StartX, int StartY, int EndX, int EndY,
  207. ;       unsigned int PageBase, char far * Pattern);
  208. ;
  209. ;
  210.  
  211. _x_rect_pattern_clipped proc
  212. ARG     StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword
  213. LOCAL   NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk
  214.     push bp                       ;preserve caller's stack frame
  215.     mov  bp,sp                    ;point to local stack frame
  216.     sub  sp,LocalStk              ;allocate space for local vars
  217.     push si                       ;preserve caller's register variables
  218.     push di
  219.     push ds
  220.  
  221.     mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top
  222.     mov   cx,[_BottomClip]
  223.     mov   ax,[StartY]
  224.     mov   bx,[EndY]
  225.     cmp   dx,ax
  226.     jle   @@CheckBottomClip
  227.     cmp   dx,bx
  228.     jg    @@NotVisible
  229.     mov   [StartY],dx
  230.  
  231. @@CheckBottomClip:
  232.     cmp   cx,bx
  233.     jg    @@CheckLeftClip
  234.     cmp   cx,ax
  235.     jl    @@NotVisible
  236.     mov   [EndY],cx
  237.  
  238. @@CheckLeftClip:
  239.     mov   dx,[_LeftClip]           ; Compare u.l. Y coord with Top
  240.     mov   cx,[_RightClip]
  241.     mov   ax,[StartX]
  242.     mov   bx,[EndX]
  243.     sal   dx,2
  244.     sal   cx,2
  245.     cmp   dx,ax
  246.     jle   @@CheckRightClip
  247.     cmp   dx,bx
  248.     jg    @@NotVisible
  249.     mov   [StartX],dx
  250.  
  251. @@CheckRightClip:
  252.     cmp   cx,bx
  253.     jg    RPClipDone
  254.     cmp   cx,ax
  255.     jl    @@NotVisible
  256.     mov   [EndX],cx
  257.     jmp   RPClipDone
  258.  
  259. @@NotVisible:
  260.     mov   ax,1
  261.     pop   ds
  262.     pop   di                          ; restore registers
  263.     pop   si
  264.     mov   sp,bp
  265.     pop   bp
  266.     ret
  267.  
  268. _x_rect_pattern_clipped endp
  269.  
  270. ;---------------------------------------------------------------------------
  271. ; Mode X (320x240, 256 colors) rectangle 4x4 pattern fill routine.
  272. ; Upper left corner of pattern is always aligned to a multiple-of-4
  273. ; row and column. Works on all VGAs. Uses approach of copying the
  274. ; pattern to off-screen display memory, then loading the latches with
  275. ; the pattern for each scan line and filling each scan line four
  276. ; pixels at a time. Fills up to but not including the column at EndX
  277. ; and the row at EndY. No clipping is performed. All ASM code tested
  278. ;
  279. ;
  280. ; Based on code originally published in DDJ Mag by M. Abrash
  281. ;
  282. ;
  283. ;  C near-callable as:
  284. ;
  285. ;    void x_rect_pattern(int StartX, int StartY, int EndX, int EndY,
  286. ;       unsigned int PageBase, char far * Pattern);
  287.  
  288.  
  289.  
  290. _x_rect_pattern proc
  291. ARG     StartX:word,StartY:word,EndX:word,EndY:word,PageBase:word,Pattern:dword
  292. LOCAL   NextScanOffset:word,RectAddrWidth:word,Height:word=LocalStk
  293.     push bp                       ;preserve caller's stack frame
  294.     mov  bp,sp                    ;point to local stack frame
  295.     sub  sp,LocalStk              ;allocate space for local vars
  296.     push si                       ;preserve caller's register variables
  297.     push di
  298.     push ds
  299.  
  300. RPClipDone:
  301.     cld
  302.     mov  ax,SCREEN_SEG            ;point ES to display memory
  303.     mov  es,ax
  304.                       ;copy pattern to display memory buffer
  305.     lds  si,dword ptr [Pattern]   ;point to pattern to fill with
  306.     mov  di,PATTERN_BUFFER        ;point ES:DI to pattern buffer
  307.     mov  dx,SC_INDEX              ;point Sequence Controller Index to
  308.     mov  al,MAP_MASK              ; Map Mask
  309.     out  dx,al
  310.     inc  dx                       ;point to SC Data register
  311.     mov  cx,4                     ;4 pixel quadruplets in pattern
  312. @@DownloadPatternLoop:
  313.     mov  al,1                     ;
  314.     out  dx,al                    ;select plane 0 for writes
  315.         movsb                         ;copy over next plane 0 pattern pixel
  316.     dec  di                       ;stay at same address for next plane
  317.     mov  al,2                     ;
  318.     out  dx,al                    ;select plane 1 for writes
  319.     movsb                         ;copy over next plane 1 pattern pixel
  320.     dec  di                       ;stay at same address for next plane
  321.     mov  al,4                     ;
  322.     out  dx,al                    ;select plane 2 for writes
  323.         movsb                         ;copy over next plane 2 pattern pixel
  324.     dec  di                       ;stay at same address for next plane
  325.     mov  al,8                     ;
  326.     out  dx,al                    ;select plane 3 for writes
  327.         movsb                         ;copy over next plane 3 pattern pixel
  328.                                       ; and advance address
  329.         loop @@DownloadPatternLoop
  330.         pop  ds
  331.  
  332.     mov  dx,GC_INDEX              ;set the bit mask to select all bits
  333.     mov  ax,00000h+BIT_MASK       ; from the latches and none from
  334.     out  dx,ax                    ; the CPU, so that we can write the
  335.                                       ; latch contents directly to memory
  336.     mov  ax,[StartY]              ;top rectangle scan line
  337.     mov  si,ax
  338.     and  si,011b                  ;top rect scan line modulo 4
  339.     add  si,PATTERN_BUFFER        ;point to pattern scan line that
  340.                       ; maps to top line of rect to draw
  341.     mov  dx,[_ScrnLogicalByteWidth]
  342.     mul  dx                       ;offset in page of top rect scan line
  343.     mov  di,[StartX]
  344.     mov  bx,di
  345.     sar  di,2             ;X/4 = offset of first rectangle pixel in scan
  346.     add  di,ax                    ;offset of first rectangle pixel in page
  347.     add  di,[PageBase]            ;offset of first rectangle pixel in
  348.                                       ; display memory
  349.     and  bx,0003h                 ;look up left edge plane mask
  350.     mov  ah,LeftClipPlaneMask[bx] ; to clip
  351.     mov  bx,[EndX]
  352.     and  bx,0003h                  ;look up right edge plane
  353.     mov  al,RightClipPlaneMask[bx] ; mask to clip
  354.     mov  bx,ax                     ;put the masks in BX
  355.  
  356.     mov  cx,[EndX]                 ;calculate # of addresses across rect
  357.     mov  ax,[StartX]
  358.     cmp  cx,ax
  359.     jle  @@FillDone                ;skip if 0 or negative width
  360.     dec  cx
  361.     and  ax,not 011b
  362.     sub  cx,ax
  363.     sar  cx,2                 ;# of addresses across rectangle to fill - 1
  364.     jnz  @@MasksSet           ;there's more than one pixel to draw
  365.     and  bh,bl                ;there's only one pixel, so combine the left
  366.                                   ; and right edge clip masks
  367. @@MasksSet:
  368.     mov  ax,[EndY]
  369.     sub  ax,[StartY]          ;AX = height of rectangle
  370.     jle  @@FillDone           ;skip if 0 or negative height
  371.     mov  [Height],ax
  372.     mov  ax,[_ScrnLogicalByteWidth]
  373.     sub  ax,cx                ;distance from end of one scan line to start
  374.     dec  ax                   ; of next
  375.     mov  [NextScanOffset],ax
  376.     mov  [RectAddrWidth],cx   ;remember width in addresses - 1
  377.     mov  dx,SC_INDEX+1        ;point to Sequence Controller Data reg
  378.                                   ; (SC Index still points to Map Mask)
  379. @@FillRowsLoop:
  380.     mov  cx,[RectAddrWidth]   ;width across - 1
  381.     mov  al,es:[si]           ;read display memory to latch this scan
  382.                                   ; line's pattern
  383.     inc  si                   ;point to the next pattern scan line, wrapping
  384.     jnz  short @@NoWrap       ; back to the start of the pattern if
  385.     sub  si,4                 ; we've run off the end
  386. @@NoWrap:
  387.     mov  al,bh                ;put left-edge clip mask in AL
  388.     out  dx,al                ;set the left-edge plane (clip) mask
  389.         stosb                     ;draw the left edge (pixels come from latches;
  390.                                   ; value written by CPU doesn't matter)
  391.     dec  cx                   ;count off left edge address
  392.     js   @@FillLoopBottom     ;that's the only address
  393.     jz   @@DoRightEdge        ;there are only two addresses
  394.     mov  al,00fh              ;middle addresses drawn 4 pixels at a pop
  395.     out  dx,al                ;set middle pixel mask to no clip
  396.     rep  stosb                ;draw middle addresses four pixels apiece
  397.                                   ; (from latches; value written doesn't matter)
  398. @@DoRightEdge:
  399.     mov  al,bl                ;put right-edge clip mask in AL
  400.     out  dx,al                ;set the right-edge plane (clip) mask
  401.         stosb                     ;draw the right edge (from latches; value
  402.                                   ; written doesn't matter)
  403. @@FillLoopBottom:
  404.     add  di,[NextScanOffset]  ;point to the start of the next scan
  405.                   ; line of the rectangle
  406.     dec  word ptr [Height]    ;count down scan lines
  407.     jnz  @@FillRowsLoop
  408. @@FillDone:
  409.     mov  dx,GC_INDEX+1        ;restore the bit mask to its default,
  410.     mov  al,0ffh              ; which selects all bits from the CPU
  411.     out  dx,al                ; and none from the latches (the GC
  412.                   ; Index still points to Bit Mask)
  413.  
  414.     pop  di                   ;restore caller's register variables
  415.     pop  si
  416.     mov  sp,bp                ;discard storage for local variables
  417.     pop  bp                   ;restore caller's stack frame
  418.         ret
  419. _x_rect_pattern endp
  420.  
  421. ;-----------------------------------------------------------------------
  422. ; Mode X (320x240, 256 colors) display memory to display memory copy
  423. ; routine. Left edge of source rectangle modulo 4 must equal left edge
  424. ; of destination rectangle modulo 4. Works on all VGAs. Uses approach
  425. ; of reading 4 pixels at a time from the source into the latches, then
  426. ; writing the latches to the destination. Copies up to but not
  427. ; including the column at SrcEndX and the row at SrcEndY. No
  428. ; clipping is performed. Results are not guaranteed if the source and
  429. ; destination overlap.
  430. ;
  431. ;
  432. ; Based on code originally published in DDJ Mag by M. Abrash
  433. ;
  434. ;C near-callable as:
  435. ;    void x_cp_vid_rect(int SrcStartX, int SrcStartY,
  436. ;       int SrcEndX, int SrcEndY, int DestStartX,
  437. ;       int DestStartY, unsigned int SrcPageBase,
  438. ;       unsigned int DestPageBase, int SrcBitmapWidth,
  439. ;       int DestBitmapWidth);
  440.  
  441. _x_cp_vid_rect proc
  442.     ARG SrcStartX:word,SrcStartY:word,SrcEndX:word,SrcEndY:word,DestStartX:word,DestStartY:word,SrcPageBase:word,DestPageBase:word,SrcBitmapW:word,DestBitmapW:word
  443.     LOCAL SrcNextOffs:word,DestNextOffs:word,RectAddrW:word,Height:word=LocalStk
  444.     push    bp                  ;preserve caller's stack frame
  445.     mov     bp,sp               ;point to local stack frame
  446.     sub     sp,LocalStk         ;allocate space for local vars
  447.     push    si                  ;preserve caller's register variables
  448.     push    di
  449.         push    ds
  450.  
  451.         cld
  452.     mov     dx,GC_INDEX         ;set the bit mask to select all bits
  453.     mov     ax,00000h+BIT_MASK  ; from the latches and none from
  454.     out dx,ax                   ; the CPU, so that we can write the
  455.                     ; latch contents directly to memory
  456.     mov     ax,SCREEN_SEG       ;point ES to display memory
  457.         mov     es,ax
  458.     mov     ax,[DestBitmapW]
  459.     shr     ax,2                ;convert to width in addresses
  460.     mul     [DestStartY]        ;top dest rect scan line
  461.     mov     di,[DestStartX]
  462.     sar     di,2                ;X/4 = offset of first dest rect pixel in
  463.                     ; scan line
  464.     add     di,ax               ;offset of first dest rect pixel in page
  465.     add     di,[DestPageBase]   ;offset of first dest rect pixel
  466.                     ; in display memory
  467.     mov     ax,[SrcBitmapW]
  468.     sar     ax,2                ;convert to width in addresses
  469.     mul     [SrcStartY]      ;top source rect scan line
  470.     mov     si,[SrcStartX]
  471.         mov     bx,si
  472.     sar     si,2              ;X/4 = offset of first source rect pixel in
  473.                   ; scan line
  474.     add     si,ax             ;offset of first source rect pixel in page
  475.     add     si,[SrcPageBase]  ;offset of first source rect
  476.                   ; pixel in display memory
  477.     and     bx,0003h                     ;look up left edge plane mask
  478.     mov     ah,LeftClipPlaneMask[bx]  ; to clip
  479.     mov     bx,[SrcEndX]
  480.     and     bx,0003h                     ;look up right edge plane
  481.     mov     al,RightClipPlaneMask[bx] ; mask to clip
  482.     mov     bx,ax                        ;put the masks in BX
  483.  
  484.     mov     cx,[SrcEndX]              ;calculate # of addresses across
  485.     mov     ax,[SrcStartX]            ; rect
  486.         cmp     cx,ax
  487.     jle     @@CopyDone                   ;skip if 0 or negative width
  488.         dec     cx
  489.         and     ax,not 011b
  490.         sub     cx,ax
  491.     sar     cx,2             ;# of addresses across rectangle to copy - 1
  492.     jnz     @@MasksSet       ;there's more than one address to draw
  493.     and     bh,bl            ;there's only one address, so combine the left
  494.                  ; and right edge clip masks
  495. @@MasksSet:
  496.     mov     ax,[SrcEndY]
  497.     sub     ax,[SrcStartY]     ;AX = height of rectangle
  498.     jle     @@CopyDone         ;skip if 0 or negative height
  499.     mov     [Height],ax
  500.     mov     ax,[DestBitmapW]
  501.     sar     ax,2               ;convert to width in addresses
  502.     sub     ax,cx              ;distance from end of one dest scan line
  503.     dec     ax                 ; to start of next
  504.     mov     [DestNextOffs],ax
  505.     mov     ax,[SrcBitmapW]
  506.     sar     ax,2               ;convert to width in addresses
  507.     sub     ax,cx              ;distance from end of one source scan line
  508.     dec     ax                 ; to start of next
  509.     mov     [SrcNextOffs],ax
  510.     mov     [RectAddrW],cx     ;remember width in addresses - 1
  511.     mov     dx,SC_INDEX+1      ;point to Sequence Controller Data reg
  512.                    ; (SC Index still points to Map Mask)
  513.     mov     ax,es              ;DS=ES=screen segment for MOVS
  514.         mov     ds,ax
  515. @@CopyRowsLoop:
  516.     mov     cx,[RectAddrW]     ;width across - 1
  517.     mov     al,bh              ;put left-edge clip mask in AL
  518.     out     dx,al              ;set the left-edge plane (clip) mask
  519.     movsb                      ;copy the left edge (pixels go through
  520.                    ; latches)
  521.     dec     cx                 ;count off left edge address
  522.     js      @@CopyLoopBottom   ;that's the only address
  523.     jz      @@DoRightEdge      ;there are only two addresses
  524.     mov     al,00fh            ;middle addresses are drawn 4 pix per go
  525.     out     dx,al              ;set the middle pixel mask to no clip
  526.     rep     movsb              ;draw the middle addresses four pix per go
  527.                    ; (pixels copied through latches)
  528. @@DoRightEdge:
  529.         mov     al,bl   ;put right-edge clip mask in AL
  530.         out     dx,al   ;set the right-edge plane (clip) mask
  531.         movsb           ;draw the right edge (pixels copied through
  532.                         ; latches)
  533. @@CopyLoopBottom:
  534.     add     si,[SrcNextOffs]   ;point to the start of
  535.     add     di,[DestNextOffs]  ; next source & dest lines
  536.     dec     word ptr [Height]  ;count down scan lines
  537.     jnz     @@CopyRowsLoop
  538. @@CopyDone:
  539.     mov     dx,GC_INDEX+1   ;restore the bit mask to its default,
  540.         mov     al,0ffh         ; which selects all bits from the CPU
  541.     out     dx,al           ; and none from the latches (the GC
  542.                                 ; Index still points to Bit Mask)
  543.         pop     ds
  544.     pop     di              ;restore caller's register variables
  545.         pop     si
  546.     mov     sp,bp           ;discard storage for local variables
  547.     pop     bp              ;restore caller's stack frame
  548.         ret
  549. _x_cp_vid_rect  endp
  550.  
  551. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  552. ; Copy a rectangular region of a VGA screen, with x coordinates
  553. ; rounded to the nearest byte -- source and destination may overlap.
  554. ;
  555. ; C near-callable as:
  556. ;
  557. ; void x_shift_rect (WORD SrcLeft, WORD SrcTop,
  558. ;                    WORD SrcRight, WORD SrcBottom,
  559. ;                    WORD DestLeft, WORD DestTop, WORD ScreenOffs);
  560. ;
  561. ; SrcRight is rounded up, and the left edges are rounded down, to ensure
  562. ; that the pixels pointed to by the arguments are inside the rectangle.
  563. ;
  564. ; The width of the rectangle in bytes (width in pixels / 4)
  565. ; cannot exceed 255.
  566. ;
  567. ; ax, bx, cx, dx, and es eat hot lead.
  568. ;
  569. ; This function was written by Matthew MacKenzie
  570. ; matm@eng.umd.edu
  571.  
  572.     align   2
  573. _x_shift_rect proc
  574. ARG     SrcLeft,SrcTop,SrcRight,SrcBottom,DestLeft,DestTop,ScreenOffs:word
  575. LOCAL   width_temp:word=LocalStk
  576.  
  577.     push bp
  578.     mov bp, sp
  579.     sub sp, LocalStk
  580.     push si
  581.     push di
  582.     push ds
  583.  
  584.     ; find values for width & x motion
  585.     mov si, SrcLeft     ; source x in bytes
  586.     sar si, 2
  587.  
  588.     mov di, DestLeft    ; destination x in bytes
  589.     sar di, 2
  590.  
  591.     mov bx, SrcRight    ; right edge of source in bytes, rounded up
  592.     add bx, 3
  593.     sar bx, 2
  594.     sub bx, si
  595.     mov ax, bx          ; width - 1
  596.     inc bx              ; we'll use this as an offset for moving up or down
  597.     mov width_temp, bx
  598.  
  599.     cld                 ; by default, strings increment
  600.  
  601.     cmp si, di
  602.     jge @@MovingLeft
  603.  
  604. ; we're moving our rectangle right, so we copy it from right to left
  605.     add si, ax          ; source & destination will start on the right edge
  606.     add di, ax
  607.     neg bx
  608.     std                 ; strings decrement
  609.  
  610. @@MovingLeft:
  611.  
  612. ; find values for height & y motion
  613.     mov cx, _ScrnLogicalByteWidth ; bytes to move to advance one line
  614.     mov ax, SrcTop
  615.     mov dx, DestTop     ; default destination y
  616.     cmp ax, dx
  617.     jge @@MovingUp
  618.  
  619. ; we're moving our rectangle down, so we copy it from bottom to top
  620.     mov ax, SrcBottom   ; source starts at bottom
  621.     add dx, ax          ; add (height - 1) to destination y
  622.     sub dx, SrcTop
  623.     neg cx              ; advance up screen rather than down
  624.  
  625. @@MovingUp:
  626.     push dx             ; save destination y during multiply
  627.     mul _ScrnLogicalByteWidth
  628.     add si, ax          ; add y in bytes to source
  629.     pop ax              ; restore destination y
  630.     mul _ScrnLogicalByteWidth
  631.     add di, ax          ; add y in bytes to destination
  632.  
  633.     sub cx, bx          ; final value for moving up or down
  634.  
  635.     add si, ScreenOffs  ; source & destination are on the same screen
  636.     add di, ScreenOffs
  637.  
  638.     mov dx, SC_INDEX    ; set map mask to all four planes
  639.     mov ax, 00f02h
  640.     out dx, ax
  641.  
  642.     mov dx, GC_INDEX    ; set bit mask to take data from latches
  643.     mov ax, BIT_MASK    ;  rather than CPU
  644.     out dx, ax
  645.  
  646.     mov ax, SCREEN_SEG  ; source and destination are VGA memory
  647.     mov es, ax
  648.     mov ds, ax
  649.  
  650.     mov ah, byte ptr width_temp ; width in bytes should fit in 8 bits
  651.  
  652.     mov bx, SrcBottom   ; height - 1
  653.     sub bx, SrcTop
  654.  
  655.     mov dx, cx          ; bytes to add to advance one line
  656.  
  657.     xor ch, ch          ; ready to rock
  658.  
  659. @@LineLoop:
  660.     mov cl, ah          ; load width in bytes
  661.     rep movsb           ; move 4 pixels at a time using latches (YOW!)
  662.  
  663.     add si, dx          ; advance source by one line
  664.     add di, dx          ; advance destination by one line
  665.  
  666.     dec bx              ; line counter
  667.     jge @@LineLoop      ; 0 still means one more to go
  668.  
  669.     mov dx, GC_INDEX + 1; set bit mask to take data from CPU (normal setting)
  670.     mov al, 0ffh
  671.     out dx, al
  672.  
  673. ; kick
  674.     pop ds
  675.     pop di
  676.     pop si
  677.     mov sp, bp
  678.     pop bp
  679.  
  680.     ret
  681. _x_shift_rect endp
  682.  
  683.     end
  684.  
  685.